﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;
using System.Reflection;
using Extensil.Common;

namespace TaskAutomation
{
    public enum PropertyType
    {
        Text,
        Combo
    }
    public class AtributeInfo
    {
        public AtributeInfo(bool isRequired, PropertyType pType, object pParam)
        {
            IsRequired = isRequired;
            PropType = pType;
            PropParam = pParam;
        }
        public bool IsRequired = false;
        public PropertyType PropType = PropertyType.Text;
        public object PropParam = null;
    }
    public class Task : ConfigurationElement
    {
        [ConfigurationProperty("name", IsRequired = true)]
        public string Name
        {
            get
            {
                return this["name"] as string;
            }
            set
            {
                this["name"] = value;
            }
        }
        [ConfigurationProperty("handler", IsRequired = true)]
        public string Handler
        {
            get
            {
                return this["handler"] as string;
            }
            set
            {
                this["handler"] = value;
            }
        }
        [ConfigurationProperty("param", IsRequired = false)]
        public string Param
        {
            get
            {
                return this["param"] as string;
            }
            set
            {
                this["param"] = value;
            }


        }
        public override bool IsReadOnly()
        {
            return false;
        }
        public static List<KeyValuePair<string, AtributeInfo>> AttributeList
        {
            get
            {
                List<KeyValuePair<string, AtributeInfo>> taskAttributes = new List<KeyValuePair<string, AtributeInfo>>();
                var props = typeof(Task).GetProperties(BindingFlags.Public | BindingFlags.Instance);
                foreach(PropertyInfo prop in props)
                {
                    if(prop.DeclaringType != typeof(Task))
                        continue;
                    bool isRequired = false;
                    PropertyType pType = PropertyType.Text;
                    object pParam = null;
                    foreach(object attr in prop.GetCustomAttributes(typeof(ConfigurationPropertyAttribute), true))
                    {
                        ConfigurationPropertyAttribute cProp = attr as ConfigurationPropertyAttribute;
                        if(null != cProp && cProp.IsRequired)
                            isRequired = true;
                    }
                    TaskSettings ts = TaskSettings.GetConfig();
                    if(prop.Name.ToLower() == "handler")
                    {
                        pType = PropertyType.Combo;
                        List<ComboPropertyParam> handlers = new List<ComboPropertyParam>();
                        foreach(Handler hnd in  ts.HandlerList)
                            handlers.Add(new ComboPropertyParam(hnd.Name, hnd.Name));
                        pParam = handlers;
                    }

                    taskAttributes.Add(new KeyValuePair<string, AtributeInfo>(prop.Name, new AtributeInfo(isRequired, pType, pParam)));
                }
                return taskAttributes;
            }
        }
    }

    public class TaskList : ConfigurationElementCollection
    {
        public Task this[int index]
        {
            get
            {
                return base.BaseGet(index) as Task;
            }
            set
            {
                if(base.Count > index && base.BaseGet(index) != null)
                {
                    base.BaseRemoveAt(index);
                }
                this.BaseAdd(index, value);
            }
        }

        public override bool IsReadOnly()
        {
            return false;
        }

        void Add(Task tsk)
        {
            this.BaseAdd(tsk);
        }
        public void AddNewTask(Task tsk)
        {
            Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
            ConfigurationSection taskSettings = config.GetSection("TaskSettings");

            TaskList taskList = ((TaskSettings)taskSettings).TaskList;

            taskList.Add(tsk);

            taskSettings.SectionInformation.ForceSave = true;
            config.Save(ConfigurationSaveMode.Modified);

            ConfigurationManager.RefreshSection("TaskSettings"); 

        }

        public void EditTask(int index, Task tsk)
        {
            Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
            ConfigurationSection taskSettings = config.GetSection("TaskSettings");

            TaskList taskList = ((TaskSettings)taskSettings).TaskList;

            taskList[index] = tsk;

            taskSettings.SectionInformation.ForceSave = true;
            config.Save(ConfigurationSaveMode.Modified);

            ConfigurationManager.RefreshSection("TaskSettings");

        }

        protected override ConfigurationElement CreateNewElement(string elementName)
        {
            return base.CreateNewElement(elementName);
        }
        protected override ConfigurationElement CreateNewElement()
        {
            return new Task();
        }

        protected override object GetElementKey(ConfigurationElement element)
        {
            return ((Task)element).Name;
        }
    }
    public class Handler :ConfigurationElement
    {
        [ConfigurationProperty("name", IsRequired = true)]
        public string Name
        {
            get
            {
                return this["name"] as string;
            }
            set
            {
                this["name"] = value;
            }
        }
        [ConfigurationProperty("path", IsRequired = true)]
        public string Path
        {
            get
            {
                return this["path"] as string;
            }
            set
            {
                this["path"] = value;
            }
        }
        public override bool IsReadOnly()
        {
            return false;
        }
        public static List<KeyValuePair<string, bool>> AttributeList
        {
            get
            {
                List<KeyValuePair<string, bool>> taskAttributes = new List<KeyValuePair<string, bool>>();
                var props = typeof(Task).GetProperties(BindingFlags.Public | BindingFlags.Instance);
                foreach(PropertyInfo prop in props)
                {
                    if(prop.DeclaringType != typeof(Handler))
                        continue;
                    bool isRequired = false;

                    foreach(object attr in prop.GetCustomAttributes(typeof(ConfigurationPropertyAttribute), true))
                    {
                        ConfigurationPropertyAttribute cProp = attr as ConfigurationPropertyAttribute;
                        if(null != cProp && cProp.IsRequired)
                            isRequired = true;
                    }

                    taskAttributes.Add(new KeyValuePair<string, bool>(prop.Name, isRequired));
                }
                return taskAttributes;
            }
        }
    }
    public class HandlerList :ConfigurationElementCollection
    {
        public Handler this[int index]
        {
            get
            {
                return base.BaseGet(index) as Handler;
            }
            set
            {
                if(base.Count > index && base.BaseGet(index) != null)
                {
                    base.BaseRemoveAt(index);
                }
                this.BaseAdd(index, value);
            }
        }
        public Handler this[string key]
        {
            get
            {
                return base.BaseGet(key) as Handler;
            }
        }

        public override bool IsReadOnly()
        {
            return false;
        }

        void Add(Handler tsk)
        {
            this.BaseAdd(tsk);
        }
        public void AddNewHandler(Handler hnd)
        {
            Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
            ConfigurationSection taskSettings = config.GetSection("TaskSettings");

            HandlerList handlerList = ((TaskSettings)taskSettings).HandlerList;

            handlerList.Add(hnd);

            taskSettings.SectionInformation.ForceSave = true;
            config.Save(ConfigurationSaveMode.Modified);

            ConfigurationManager.RefreshSection("TaskSettings");

        }

        public void EditHandler(int index, Handler hnd)
        {
            Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
            ConfigurationSection taskSettings = config.GetSection("TaskSettings");

            HandlerList handlerList = ((TaskSettings)taskSettings).HandlerList;

            handlerList[index] = hnd;

            taskSettings.SectionInformation.ForceSave = true;
            config.Save(ConfigurationSaveMode.Modified);

            ConfigurationManager.RefreshSection("TaskSettings");

        }

        protected override ConfigurationElement CreateNewElement(string elementName)
        {
            return base.CreateNewElement(elementName);
        }
        protected override ConfigurationElement CreateNewElement()
        {
            return new Handler();
        }

        protected override object GetElementKey(ConfigurationElement element)
        {
            return ((Handler)element).Name;
        }
    }
    public class TaskSettings
        :ConfigurationSection
    {

        public static TaskSettings GetConfig()
        {
            return (TaskSettings)System.Configuration.ConfigurationManager.GetSection("TaskSettings") ?? new TaskSettings();
        }
        [System.Configuration.ConfigurationProperty("logFormat")]
        public string TaskLogFormat
        {
            get
            {
                return (string)this["logFormat"];
            }
        }

        [ConfigurationProperty("dateFormat")]
        public string DateFormat
        {
            get
            {
                return (string)this["dateFormat"];
            }
        }

        [ConfigurationProperty("TaskList")]
        [ConfigurationCollection(typeof(TaskList), AddItemName = "Task")]
        public TaskList TaskList
        {
            get
            {
                object o = this["TaskList"];
                return o as TaskList;
            }
        }

        [ConfigurationProperty("HandlerList")]
        [ConfigurationCollection(typeof(HandlerList), AddItemName = "Handler")]
        public HandlerList HandlerList
        {
            get
            {
                object o = this["HandlerList"];
                return o as HandlerList;
            }
        }
    }
}
